/**
 * 数据同步管理器
 * 处理本地数据与云端的同步，包括冲突解决和离线支持
 */

import stateManager, { STATE_TYPES, getState, setState } from './stateManager.js'
import { getTestHistory, saveTestRecord } from './testHistory.js'
import { getAchievements } from './achievementManager.js'
import { getTestStats } from './testHistory.js'

/**
 * 同步状态枚举
 */
export const SYNC_STATUS = {
	IDLE: 'idle',
	SYNCING: 'syncing',
	SUCCESS: 'success',
	ERROR: 'error',
	CONFLICT: 'conflict'
}

/**
 * 同步类型枚举
 */
export const SYNC_TYPES = {
	FULL: 'full',
	INCREMENTAL: 'incremental',
	FORCE_UPLOAD: 'force_upload',
	FORCE_DOWNLOAD: 'force_download'
}

/**
 * 冲突解决策略
 */
export const CONFLICT_RESOLUTION = {
	LOCAL_WINS: 'local_wins',
	REMOTE_WINS: 'remote_wins',
	MERGE: 'merge',
	MANUAL: 'manual'
}

/**
 * 数据同步管理器类
 */
class SyncManager {
	constructor() {
		this.isOnline = true
		this.syncQueue = []
		this.conflictQueue = []
		this.syncInProgress = false
		this.lastSyncTime = null
		this.syncInterval = null
		this.retryCount = 0
		this.maxRetries = 3
		this.syncSettings = {
			enabled: true,
			autoSync: true,
			syncInterval: 5 * 60 * 1000, // 5分钟
			conflictResolution: CONFLICT_RESOLUTION.MERGE,
			maxOfflineActions: 100,
			compressData: true,
			encryptData: false
		}
		
		this.init()
	}
	
	/**
	 * 初始化同步管理器
	 */
	init() {
		this.loadSyncSettings()
		this.setupNetworkListener()
		this.setupAutoSync()
		this.loadOfflineQueue()
		this.loadLastSyncTime()
	}
	
	/**
	 * 加载同步设置
	 */
	loadSyncSettings() {
		try {
			if (typeof uni !== 'undefined') {
				const saved = uni.getStorageSync('sync_settings')
				if (saved) {
					this.syncSettings = { ...this.syncSettings, ...saved }
				}
			}
		} catch (error) {
			console.error('加载同步设置失败:', error)
		}
	}
	
	/**
	 * 保存同步设置
	 */
	saveSyncSettings() {
		try {
			if (typeof uni !== 'undefined') {
				uni.setStorageSync('sync_settings', this.syncSettings)
			}
		} catch (error) {
			console.error('保存同步设置失败:', error)
		}
	}
	
	/**
	 * 设置网络监听器
	 */
	setupNetworkListener() {
		// 监听网络状态变化
		stateManager.on('networkChanged', (isOnline) => {
			this.isOnline = isOnline
			if (isOnline && this.syncQueue.length > 0) {
				// 网络恢复时处理离线队列
				this.processOfflineQueue()
			}
		})
	}
	
	/**
	 * 设置自动同步
	 */
	setupAutoSync() {
		if (this.syncSettings.autoSync && this.syncSettings.enabled) {
			this.syncInterval = setInterval(() => {
				if (this.isOnline && !this.syncInProgress) {
					this.sync(SYNC_TYPES.INCREMENTAL)
				}
			}, this.syncSettings.syncInterval)
		}
	}
	
	/**
	 * 加载离线队列
	 */
	loadOfflineQueue() {
		try {
			if (typeof uni !== 'undefined') {
				const queue = uni.getStorageSync('sync_queue')
				if (queue && Array.isArray(queue)) {
					this.syncQueue = queue
				}
			}
		} catch (error) {
			console.error('加载离线队列失败:', error)
		}
	}
	
	/**
	 * 保存离线队列
	 */
	saveOfflineQueue() {
		try {
			if (typeof uni !== 'undefined') {
				uni.setStorageSync('sync_queue', this.syncQueue)
			}
		} catch (error) {
			console.error('保存离线队列失败:', error)
		}
	}
	
	/**
	 * 加载最后同步时间
	 */
	loadLastSyncTime() {
		try {
			if (typeof uni !== 'undefined') {
				this.lastSyncTime = uni.getStorageSync('last_sync_time')
			}
		} catch (error) {
			console.error('加载最后同步时间失败:', error)
		}
	}
	
	/**
	 * 保存最后同步时间
	 */
	saveLastSyncTime() {
		try {
			if (typeof uni !== 'undefined') {
				uni.setStorageSync('last_sync_time', this.lastSyncTime)
			}
		} catch (error) {
			console.error('保存最后同步时间失败:', error)
		}
	}
	
	/**
	 * 开始同步
	 * @param {string} type - 同步类型
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async sync(type = SYNC_TYPES.INCREMENTAL, options = {}) {
		if (!this.syncSettings.enabled) {
			return { status: SYNC_STATUS.ERROR, message: '同步已禁用' }
		}
		
		if (this.syncInProgress) {
			return { status: SYNC_STATUS.ERROR, message: '同步正在进行中' }
		}
		
		if (!this.isOnline) {
			return { status: SYNC_STATUS.ERROR, message: '网络不可用' }
		}
		
		this.syncInProgress = true
		setState(STATE_TYPES.UI, { loading: true, loadingText: '正在同步数据...' })
		
		try {
			const result = await this.performSync(type, options)
			this.retryCount = 0
			this.lastSyncTime = new Date().toISOString()
			this.saveLastSyncTime()
			
			// 触发同步完成事件
			stateManager.emit('syncCompleted', result)
			
			return result
		} catch (error) {
			console.error('同步失败:', error)
			this.retryCount++
			
			if (this.retryCount < this.maxRetries) {
				// 延迟重试
				setTimeout(() => {
					this.sync(type, options)
				}, 1000 * Math.pow(2, this.retryCount))
			}
			
			return {
				status: SYNC_STATUS.ERROR,
				message: error.message,
				retryCount: this.retryCount
			}
		} finally {
			this.syncInProgress = false
			setState(STATE_TYPES.UI, { loading: false, loadingText: '' })
		}
	}
	
	/**
	 * 执行同步操作
	 * @param {string} type - 同步类型
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async performSync(type, options) {
		switch (type) {
			case SYNC_TYPES.FULL:
				return await this.fullSync(options)
			case SYNC_TYPES.INCREMENTAL:
				return await this.incrementalSync(options)
			case SYNC_TYPES.FORCE_UPLOAD:
				return await this.forceUpload(options)
			case SYNC_TYPES.FORCE_DOWNLOAD:
				return await this.forceDownload(options)
			default:
				throw new Error(`未知的同步类型: ${type}`)
		}
	}
	
	/**
	 * 完整同步
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async fullSync(options) {
		const localData = await this.getLocalData()
		const remoteData = await this.getRemoteData()
		
		const conflicts = this.detectConflicts(localData, remoteData)
		
		if (conflicts.length > 0) {
			const resolvedData = await this.resolveConflicts(conflicts, options.conflictResolution)
			await this.applyResolvedData(resolvedData)
		}
		
		// 上传本地更改
		const uploadResult = await this.uploadLocalChanges(localData)
		
		// 下载远程更改
		const downloadResult = await this.downloadRemoteChanges(remoteData)
		
		return {
			status: SYNC_STATUS.SUCCESS,
			type: SYNC_TYPES.FULL,
			uploaded: uploadResult.count,
			downloaded: downloadResult.count,
			conflicts: conflicts.length,
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 增量同步
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async incrementalSync(options) {
		const lastSync = this.lastSyncTime || new Date(0).toISOString()
		
		// 获取自上次同步以来的本地更改
		const localChanges = await this.getLocalChanges(lastSync)
		
		// 获取自上次同步以来的远程更改
		const remoteChanges = await this.getRemoteChanges(lastSync)
		
		const conflicts = this.detectConflicts(localChanges, remoteChanges)
		
		if (conflicts.length > 0) {
			const resolvedData = await this.resolveConflicts(conflicts, options.conflictResolution)
			await this.applyResolvedData(resolvedData)
		}
		
		// 上传本地更改
		const uploadResult = await this.uploadChanges(localChanges)
		
		// 应用远程更改
		const applyResult = await this.applyRemoteChanges(remoteChanges)
		
		return {
			status: SYNC_STATUS.SUCCESS,
			type: SYNC_TYPES.INCREMENTAL,
			uploaded: uploadResult.count,
			applied: applyResult.count,
			conflicts: conflicts.length,
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 强制上传
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async forceUpload(options) {
		const localData = await this.getLocalData()
		const uploadResult = await this.uploadLocalChanges(localData, true)
		
		return {
			status: SYNC_STATUS.SUCCESS,
			type: SYNC_TYPES.FORCE_UPLOAD,
			uploaded: uploadResult.count,
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 强制下载
	 * @param {Object} options - 同步选项
	 * @returns {Promise<Object>} 同步结果
	 */
	async forceDownload(options) {
		const remoteData = await this.getRemoteData()
		const downloadResult = await this.downloadRemoteChanges(remoteData, true)
		
		return {
			status: SYNC_STATUS.SUCCESS,
			type: SYNC_TYPES.FORCE_DOWNLOAD,
			downloaded: downloadResult.count,
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 获取本地数据
	 * @returns {Promise<Object>} 本地数据
	 */
	async getLocalData() {
		return {
			testHistory: getTestHistory(),
			achievements: getAchievements(),
			statistics: getTestStats(),
			settings: getState(STATE_TYPES.SETTINGS),
			user: getState(STATE_TYPES.USER),
			game: getState(STATE_TYPES.GAME),
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 获取远程数据
	 * @returns {Promise<Object>} 远程数据
	 */
	async getRemoteData() {
		// 模拟API调用
		return new Promise((resolve) => {
			setTimeout(() => {
				resolve({
					testHistory: [],
					achievements: [],
					statistics: {},
					settings: {},
					user: {},
					game: {},
					timestamp: new Date().toISOString()
				})
			}, 1000)
		})
	}
	
	/**
	 * 获取本地更改
	 * @param {string} since - 起始时间
	 * @returns {Promise<Object>} 本地更改
	 */
	async getLocalChanges(since) {
		const allData = await this.getLocalData()
		
		// 过滤出指定时间之后的更改
		const changes = {
			testHistory: allData.testHistory.filter(record => 
				new Date(record.timestamp) > new Date(since)
			),
			achievements: allData.achievements.filter(achievement => 
				new Date(achievement.unlockedAt) > new Date(since)
			),
			statistics: allData.statistics,
			settings: allData.settings,
			user: allData.user,
			game: allData.game
		}
		
		return changes
	}
	
	/**
	 * 获取远程更改
	 * @param {string} since - 起始时间
	 * @returns {Promise<Object>} 远程更改
	 */
	async getRemoteChanges(since) {
		// 模拟API调用
		return new Promise((resolve) => {
			setTimeout(() => {
				resolve({
					testHistory: [],
					achievements: [],
					statistics: {},
					settings: {},
					user: {},
					game: {}
				})
			}, 500)
		})
	}
	
	/**
	 * 检测冲突
	 * @param {Object} localData - 本地数据
	 * @param {Object} remoteData - 远程数据
	 * @returns {Array} 冲突列表
	 */
	detectConflicts(localData, remoteData) {
		const conflicts = []
		
		// 检测设置冲突
		if (this.hasConflict(localData.settings, remoteData.settings)) {
			conflicts.push({
				type: 'settings',
				local: localData.settings,
				remote: remoteData.settings
			})
		}
		
		// 检测用户数据冲突
		if (this.hasConflict(localData.user, remoteData.user)) {
			conflicts.push({
				type: 'user',
				local: localData.user,
				remote: remoteData.user
			})
		}
		
		// 检测游戏数据冲突
		if (this.hasConflict(localData.game, remoteData.game)) {
			conflicts.push({
				type: 'game',
				local: localData.game,
				remote: remoteData.game
			})
		}
		
		return conflicts
	}
	
	/**
	 * 检查是否有冲突
	 * @param {Object} local - 本地数据
	 * @param {Object} remote - 远程数据
	 * @returns {boolean} 是否有冲突
	 */
	hasConflict(local, remote) {
		if (!local || !remote) return false
		
		// 简单的时间戳比较
		const localTime = new Date(local.lastModified || 0)
		const remoteTime = new Date(remote.lastModified || 0)
		
		// 如果两个时间戳都存在且不相等，则可能有冲突
		return localTime.getTime() !== remoteTime.getTime() && 
			   Math.abs(localTime.getTime() - remoteTime.getTime()) > 1000 // 1秒容差
	}
	
	/**
	 * 解决冲突
	 * @param {Array} conflicts - 冲突列表
	 * @param {string} strategy - 解决策略
	 * @returns {Promise<Object>} 解决后的数据
	 */
	async resolveConflicts(conflicts, strategy = this.syncSettings.conflictResolution) {
		const resolvedData = {}
		
		for (const conflict of conflicts) {
			switch (strategy) {
				case CONFLICT_RESOLUTION.LOCAL_WINS:
					resolvedData[conflict.type] = conflict.local
					break
				case CONFLICT_RESOLUTION.REMOTE_WINS:
					resolvedData[conflict.type] = conflict.remote
					break
				case CONFLICT_RESOLUTION.MERGE:
					resolvedData[conflict.type] = this.mergeData(conflict.local, conflict.remote)
					break
				case CONFLICT_RESOLUTION.MANUAL:
					// 添加到冲突队列，等待用户手动解决
					this.conflictQueue.push(conflict)
					break
			}
		}
		
		return resolvedData
	}
	
	/**
	 * 合并数据
	 * @param {Object} local - 本地数据
	 * @param {Object} remote - 远程数据
	 * @returns {Object} 合并后的数据
	 */
	mergeData(local, remote) {
		if (!local) return remote
		if (!remote) return local
		
		// 简单的合并策略：取较新的值
		const merged = { ...local }
		
		Object.keys(remote).forEach(key => {
			if (remote[key] !== undefined) {
				// 如果远程值更新，使用远程值
				const localTime = new Date(local[key + '_modified'] || 0)
				const remoteTime = new Date(remote[key + '_modified'] || 0)
				
				if (remoteTime > localTime) {
					merged[key] = remote[key]
					merged[key + '_modified'] = remote[key + '_modified']
				}
			}
		})
		
		return merged
	}
	
	/**
	 * 应用解决后的数据
	 * @param {Object} resolvedData - 解决后的数据
	 */
	async applyResolvedData(resolvedData) {
		Object.entries(resolvedData).forEach(([type, data]) => {
			switch (type) {
				case 'settings':
					setState(STATE_TYPES.SETTINGS, data)
					break
				case 'user':
					setState(STATE_TYPES.USER, data)
					break
				case 'game':
					setState(STATE_TYPES.GAME, data)
					break
			}
		})
	}
	
	/**
	 * 上传本地更改
	 * @param {Object} data - 要上传的数据
	 * @param {boolean} force - 是否强制上传
	 * @returns {Promise<Object>} 上传结果
	 */
	async uploadLocalChanges(data, force = false) {
		// 模拟API调用
		return new Promise((resolve) => {
			setTimeout(() => {
				resolve({
					success: true,
					count: Object.keys(data).length,
					timestamp: new Date().toISOString()
				})
			}, 1500)
		})
	}
	
	/**
	 * 上传更改
	 * @param {Object} changes - 要上传的更改
	 * @returns {Promise<Object>} 上传结果
	 */
	async uploadChanges(changes) {
		return this.uploadLocalChanges(changes)
	}
	
	/**
	 * 下载远程更改
	 * @param {Object} data - 远程数据
	 * @param {boolean} force - 是否强制下载
	 * @returns {Promise<Object>} 下载结果
	 */
	async downloadRemoteChanges(data, force = false) {
		// 应用远程数据到本地
		if (data.testHistory && data.testHistory.length > 0) {
			data.testHistory.forEach(record => {
				saveTestRecord(record.testType, record)
			})
		}
		
		if (data.settings) {
			setState(STATE_TYPES.SETTINGS, data.settings)
		}
		
		if (data.user) {
			setState(STATE_TYPES.USER, data.user)
		}
		
		if (data.game) {
			setState(STATE_TYPES.GAME, data.game)
		}
		
		return {
			success: true,
			count: Object.keys(data).length,
			timestamp: new Date().toISOString()
		}
	}
	
	/**
	 * 应用远程更改
	 * @param {Object} changes - 远程更改
	 * @returns {Promise<Object>} 应用结果
	 */
	async applyRemoteChanges(changes) {
		return this.downloadRemoteChanges(changes)
	}
	
	/**
	 * 添加到离线队列
	 * @param {Object} action - 要添加的动作
	 */
	addToOfflineQueue(action) {
		if (this.syncQueue.length >= this.syncSettings.maxOfflineActions) {
			// 移除最旧的动作
			this.syncQueue.shift()
		}
		
		this.syncQueue.push({
			...action,
			timestamp: new Date().toISOString(),
			id: Date.now() + Math.random()
		})
		
		this.saveOfflineQueue()
	}
	
	/**
	 * 处理离线队列
	 */
	async processOfflineQueue() {
		if (this.syncQueue.length === 0) return
		
		const queue = [...this.syncQueue]
		this.syncQueue = []
		
		for (const action of queue) {
			try {
				await this.processOfflineAction(action)
			} catch (error) {
				console.error('处理离线动作失败:', error)
				// 重新添加到队列
				this.syncQueue.push(action)
			}
		}
		
		this.saveOfflineQueue()
	}
	
	/**
	 * 处理离线动作
	 * @param {Object} action - 离线动作
	 */
	async processOfflineAction(action) {
		switch (action.type) {
			case 'test_record':
				await this.uploadChanges({ testHistory: [action.data] })
				break
			case 'achievement':
				await this.uploadChanges({ achievements: [action.data] })
				break
			case 'settings':
				await this.uploadChanges({ settings: action.data })
				break
			default:
				console.warn('未知的离线动作类型:', action.type)
		}
	}
	
	/**
	 * 获取同步状态
	 * @returns {Object} 同步状态
	 */
	getSyncStatus() {
		return {
			isOnline: this.isOnline,
			syncInProgress: this.syncInProgress,
			lastSyncTime: this.lastSyncTime,
			offlineQueueSize: this.syncQueue.length,
			conflictQueueSize: this.conflictQueue.length,
			retryCount: this.retryCount,
			settings: this.syncSettings
		}
	}
	
	/**
	 * 更新同步设置
	 * @param {Object} settings - 新的设置
	 */
	updateSyncSettings(settings) {
		this.syncSettings = { ...this.syncSettings, ...settings }
		this.saveSyncSettings()
		
		// 重新设置自动同步
		if (this.syncInterval) {
			clearInterval(this.syncInterval)
			this.syncInterval = null
		}
		
		this.setupAutoSync()
	}
	
	/**
	 * 清除离线队列
	 */
	clearOfflineQueue() {
		this.syncQueue = []
		this.saveOfflineQueue()
	}
	
	/**
	 * 清除冲突队列
	 */
	clearConflictQueue() {
		this.conflictQueue = []
	}
	
	/**
	 * 手动解决冲突
	 * @param {string} conflictId - 冲突ID
	 * @param {string} resolution - 解决方案
	 * @param {Object} data - 解决数据
	 */
	async resolveConflictManually(conflictId, resolution, data) {
		const conflictIndex = this.conflictQueue.findIndex(c => c.id === conflictId)
		if (conflictIndex === -1) {
			throw new Error('冲突不存在')
		}
		
		const conflict = this.conflictQueue[conflictIndex]
		let resolvedData
		
		switch (resolution) {
			case 'use_local':
				resolvedData = conflict.local
				break
			case 'use_remote':
				resolvedData = conflict.remote
				break
			case 'use_custom':
				resolvedData = data
				break
			default:
				throw new Error('无效的解决方案')
		}
		
		// 应用解决方案
		await this.applyResolvedData({ [conflict.type]: resolvedData })
		
		// 从队列中移除
		this.conflictQueue.splice(conflictIndex, 1)
		
		// 上传解决后的数据
		await this.uploadChanges({ [conflict.type]: resolvedData })
	}
	
	/**
	 * 获取冲突列表
	 * @returns {Array} 冲突列表
	 */
	getConflicts() {
		return [...this.conflictQueue]
	}
	
	/**
	 * 销毁同步管理器
	 */
	destroy() {
		if (this.syncInterval) {
			clearInterval(this.syncInterval)
		}
		
		this.saveOfflineQueue()
		this.saveSyncSettings()
		this.saveLastSyncTime()
	}
}

// 创建全局实例
const syncManager = new SyncManager()

// 便捷方法
export const sync = (type, options) => {
	return syncManager.sync(type, options)
}

export const getSyncStatus = () => {
	return syncManager.getSyncStatus()
}

export const updateSyncSettings = (settings) => {
	syncManager.updateSyncSettings(settings)
}

export const addToOfflineQueue = (action) => {
	syncManager.addToOfflineQueue(action)
}

export const getConflicts = () => {
	return syncManager.getConflicts()
}

export const resolveConflictManually = (conflictId, resolution, data) => {
	return syncManager.resolveConflictManually(conflictId, resolution, data)
}

export const clearOfflineQueue = () => {
	syncManager.clearOfflineQueue()
}

export const clearConflictQueue = () => {
	syncManager.clearConflictQueue()
}

// 导出管理器实例
export default syncManager